home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume89 / unix / unshar.1 < prev    next >
Internet Message Format  |  1989-05-03  |  37KB

  1. Path: xanth!ames!oliveb!sun!rishathra!page
  2. From: page%rishathra@Sun.COM (Bob Page)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v89i116:  unshar - unpack shell archives
  5. Message-ID: <102572@sun.Eng.Sun.COM>
  6. Date: 3 May 89 08:02:45 GMT
  7. Sender: news@sun.Eng.Sun.COM
  8. Lines: 1146
  9. Approved: page@sun.com
  10.  
  11. Submitted-by: ecarroll@vax1.tcd.ie (Eddy Carroll)
  12. Posting-number: Volume 89, Issue 116
  13. Archive-name: unix/unshar.1
  14.  
  15. This is yet another unshar utility.  In brief: It's small, fast,
  16. handles all cat & sed format's I've seen (including multi-char sed
  17. strips), sub-directories, "./" type filenames and more.
  18.  
  19. [uuencode executable included.  ..bob]
  20.  
  21. # This is a shell archive.
  22. # Remove anything above and including the cut line.
  23. # Then run the rest of the file through 'sh'.
  24. # Unpacked files will be owned by you and have default permissions.
  25. #----cut here-----cut here-----cut here-----cut here----#
  26. #!/bin/sh
  27. # shar: SHell ARchive
  28. # Run the following text through 'sh' to create:
  29. #    makefile
  30. #    tiny.a
  31. #    unshar.c
  32. #    unshar.doc
  33. #    unshar.n
  34. #    unshar.uu
  35. # This is archive 1 of a 1-part kit.
  36. # This archive created: Wed May  3 00:57:54 1989
  37. echo "extracting makefile"
  38. sed 's/^X//' << \SHAR_EOF > makefile
  39. X#
  40. X# Aztec Make makefile, for Lattice C V4.0 :-)
  41. X#
  42. X# Unshar by Eddy Carroll, April 1989
  43. X#
  44. X
  45. XZOOEXE = unshar unshar.doc
  46. XZOOSRC = unshar.c tiny.a tiny.o unshar.n makefile
  47. XOBJS   = tiny.o unshar.o
  48. X#
  49. X#
  50. X#
  51. X.c.o:
  52. X    lc -s -v $*.c
  53. X.a.o:
  54. X    sys:lattice/c/asm -isys:include/ -u $*.a
  55. X.n.doc:
  56. X    nro >$*.doc -ms:an $*.n
  57. X#
  58. X#
  59. X#
  60. Xall: unshar unshar.doc
  61. X
  62. Xunshar: $(OBJS)
  63. X    blink from $(OBJS) to unshar sc sd nd map ram:map lib lib:lc.lib
  64. X
  65. Xtiny.o:    tiny.a
  66. Xunshar.o: unshar.c
  67. Xunshar.doc: unshar.n
  68. X
  69. Xzoo:    unshar.zoo
  70. Xzoosrc: unsharsrc.zoo
  71. X
  72. Xunshar.zoo: $(ZOOEXE)
  73. X    -delete unshar.zoo
  74. X    zoo a unshar.zoo $(ZOOEXE)
  75. X
  76. Xunsharsrc.zoo: $(ZOOSRC)
  77. X    -delete unsharsrc.zoo
  78. X    zoo a unsharsrc.zoo $(ZOOSRC)
  79. X
  80. Xclean:
  81. X    -delete "#?.bak"
  82. SHAR_EOF
  83. echo "extracting tiny.a"
  84. sed 's/^X//' << \SHAR_EOF > tiny.a
  85. X*:ts=8
  86. X****************************************************************************
  87. X*                                                                          *
  88. X* TINY.A                                  (C) Copyright Eddy Carroll 1989  *
  89. X* ~~~~~~                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  *
  90. X*                                                                          *
  91. X* This is a rewrite of the startup code provided with Lattice C V4.0.      *
  92. X* It is a "bare bones" version, which is substantially smaller, and also   *
  93. X* allows programs to be linked without needing to access lc.lib (unless    *
  94. X* of course they are using functions in lc.lib). Only CLI programs are     *
  95. X* supported, and no default i/o channels or other lattice-specific stuff   *
  96. X* are initialised. exit() doesn't automatically clean up any more, so      *
  97. X* don't use things like malloc() and fopen() unless you call free() and    *
  98. X* fclose() yourself. This replacement is designed for programs that go     *
  99. X* directly to AmigaDOS and Exec, rather than through the Unix-like Lattice *
  100. X* functions.                                                               *
  101. X*                                                                          *
  102. X* All in all, this version shaves around 1500 bytes off the size of a C    *
  103. X* program. No guarantees are supplied as regards its suitability for any   *
  104. X* particular use, other than it works for me.                              *
  105. X*                                                                          *
  106. X* Using it is very simple: Simply modify the command line for BLINK from   *
  107. X* BLINK FROM LIB:C.O+.... to BLINK FROM TINY.O+... and leave everything    *
  108. X* else the same.                                                           *
  109. X*                                                                          *
  110. X* Note that when assembling this, make sure to specify the -u switch on    *
  111. X* the Lattice assembler's command line. This adds a '_' to all symbols     *
  112. X* defined. If you are using a different assembler, you need to add a '_'   *
  113. X* manually yourself.                                                       *
  114. X*                                                                          *
  115. X****************************************************************************
  116. X
  117. X        INCLUDE "exec/types.i"
  118. X        INCLUDE "exec/alerts.i"
  119. X        INCLUDE "exec/nodes.i"
  120. X        INCLUDE "exec/lists.i"
  121. X        INCLUDE "exec/ports.i"
  122. X        INCLUDE "exec/libraries.i"
  123. X        INCLUDE "exec/tasks.i"
  124. X        INCLUDE "libraries/dos.i"
  125. X        INCLUDE "libraries/dosextens.i"
  126. X        INCLUDE "workbench/startup.i"
  127. X        INCLUDE "exec/funcdef.i"
  128. X        INCLUDE "exec/exec_lib.i"
  129. X        INCLUDE "libraries/dos_lib.i"
  130. X
  131. XMAXARGS        EQU 32    ; Maximum number of command line arguments from CLI
  132. XAbsExecBase EQU 4    ; Welcome to the only fixed point in the universe
  133. X
  134. X* A useful macro to let us call library routines
  135. Xcallsys macro
  136. X        CALLLIB _LVO\1
  137. X        endm
  138. X        
  139. X        xdef    XCEXIT            * exit(code) is standard way to exit C.
  140. X    xdef    exit                    *
  141. X
  142. X        xref    LinkerDB            * linker defined base value
  143. X        xref    _BSSBAS            * linker defined base of BSS
  144. X        xref    _BSSLEN            * linker defined length of BSS
  145. X
  146. X*       library references
  147. X
  148. X        csect   text,0,0,1,2        * xref's after this are 16-bit reloc
  149. X
  150. X        xref    main            * Name of C program to start with.
  151. X
  152. Xstart:
  153. X        movem.l d1-d6/a0-a6,-(a7)
  154. XREGSIZE EQU     (6+7)*4
  155. X        lea     REGSIZE(a7),A5         * Determine old stack pointer
  156. X        move.l  a0,a2                  * Save command pointer
  157. X        move.l  d0,d2                  * and command length
  158. X        lea     LinkerDB,a4            * Load base register
  159. X
  160. X        move.l  AbsExecBase.W,a6
  161. X        move.l  a6,SysBase(A4)
  162. X        move.l  a7,_StackPtr(A4)       * Save stack ptr
  163. X
  164. X    suba.l    a1,a1
  165. X    callsys    FindTask           * Find out our task ID
  166. X    move.l    d0,a3
  167. X
  168. X*=======================================================================
  169. X*====== CLI Startup Code ===============================================
  170. X*=======================================================================
  171. X*
  172. X* Entry: D2 = command length
  173. X*        A2 = Command pointer
  174. XfromCLI:
  175. X        move.l  a5,D0           * get top of stack
  176. X        sub.l   4(a5),D0        * compute bottom 
  177. X        add.l   #128,D0         * allow for parms overflow
  178. X        move.l  D0,_base(A4)    * save for stack checking
  179. X*-----------------------------------------------------------------------
  180. X*  Open the DOS library:
  181. X
  182. XopenDOS
  183. X    lea     DOSName(A4),A1
  184. X    moveq.l #0,D0
  185. X    callsys OpenLibrary
  186. X    move.l  D0,DOSBase(A4)
  187. X    bne    getcom
  188. XnoDOS:
  189. X    moveq.l #100,d0
  190. X    bra     exit2
  191. X
  192. X*------ find command name:
  193. Xgetcom:
  194. X    move.l  pr_CLI(a3),a0
  195. X        add.l   a0,a0           * bcpl pointer conversion
  196. X        add.l   a0,a0
  197. X        move.l  cli_CommandName(a0),a1
  198. X        add.l   a1,a1           * bcpl pointer conversion
  199. X        add.l   a1,a1
  200. X
  201. X*------ collect parameters:
  202. X        move.l  d2,d0                   * get command line length
  203. X        moveq.l #0,d1
  204. X        move.b  (a1)+,d1
  205. X        move.l  a1,_ProgramName(A4)
  206. X        add.l   d1,d0                   * add length of command name
  207. X        addq.l  #1,d0                   * allow for space after command 
  208. X
  209. X        clr.w   -(A7)                   * set null terminator for command line
  210. X        addq.l  #1,D0                   * force to even number of bytes
  211. X        andi.w  #$fffe,D0               * (round up)
  212. X        sub.l   D0,A7                   * make room on stack for command line
  213. X        subq.l  #2,D0
  214. X        clr.w   0(A7,D0)
  215. X
  216. X*------ copy command line onto stack
  217. X        move.l  d2,d0                   * get command line length
  218. X        subq.l  #1,d0
  219. X        add.l   d1,d2
  220. X
  221. Xcopy_line:
  222. X        move.b  0(A2,D0.W),0(A7,D2.W)   * copy command line to stack
  223. X        subq.l  #1,d2
  224. X        dbf     d0,copy_line
  225. X        move.b  #' ',0(a7,d2.w)         * add space between command and parms
  226. X        subq.l  #1,d2
  227. X
  228. Xcopy_cmd:
  229. X        move.b  0(a1,d2.w),0(a7,d2.w)    * copy command name to stack
  230. X        dbf     d2,copy_cmd
  231. X    move.l    a7,a1            * Get pointer to new command line
  232. X
  233. X    sub.l    #(MAXARGS*4),a7        * Reserve space for argv[]
  234. X    move.l    a7,a2            * Initialise base into array
  235. X    move.l    a2,a3            * Save base of argv
  236. X    moveq    #0,d2            * Initialise argc
  237. X
  238. X*
  239. X* From here on down, A1 is pointer into command line
  240. X*
  241. Xbuild_argv:
  242. X    bsr.s    getnext            * Read next character from line
  243. X    bcs.s    doquote            * If quote, handle
  244. X    beq.s    build_argv        * If white space, skip over it
  245. X
  246. X    lea    -1(a1),a0        * Get address of this parameter
  247. X    bsr.s    bumpargv        * Store it to argv[] array
  248. Xbuild_2:
  249. X    bsr.s    getnext            * Get next character
  250. X    bne.s    build_2            * If not white space, keep looking
  251. X    clr.b    -1(a1)            * Zero-terminate current argument
  252. X    bra.s    build_argv        * And go back to get next argument
  253. X
  254. Xdoquote:
  255. X    move.l    a1,a0            * Get pointer to this argument
  256. X    bsr.s    bumpargv        * Output it to argv[]
  257. Xquote_2:
  258. X    bsr.s    getnext            * Get next character
  259. X    bcc.s    quote_2            * If not quote, keep looking
  260. X    clr.b    -1(a1)            * Zero-terminate current argument
  261. Xquote_3:
  262. X    bsr.s    getnext            * Get next character
  263. X    bne.s    quote_3            * Skip until space reached
  264. X    beq.s    build_argv        * Go back and read next argument
  265. X
  266. Xbumpargv:
  267. X    move.l    a0,(a2)+        * Output ptr to current argument
  268. X    addq    #1,d2            * Increment argc
  269. X    cmpi    #MAXARGS,d2        * Used up all our arguments yet?
  270. X    bls.s    qrts            * If not, then return
  271. X    moveq    #110,d0            * Else set return code
  272. X    bra.s    exit2            * And exit
  273. X
  274. X*
  275. X* Reads next character from command line. If zero, never returns, but
  276. X* drops into call to main. Else, returns, with C=1 if character is quote,
  277. X* Z=1 if character is white space.
  278. X*
  279. Xgetnext:
  280. X    move.b    (a1)+,d0        * Get character from command line
  281. X    beq.s    get_2            * Exit if end of line
  282. X    cmp.b    #34,d0            * Check if quote
  283. X    beq.s    isquote            * 
  284. X    cmp.b    #32,d0            * Check if space
  285. X    beq.s    isspace            *
  286. X    cmp.b    #9,d0            * Or tab
  287. X    beq.s    isspace            *
  288. X    cmp.b    #10,d0            * Or end of line
  289. Xisspace:
  290. X    andi    #$1E,ccr        * Clear carry flag, retaining Z
  291. Xqrts    rts
  292. X
  293. Xisquote:
  294. X    ori    #1,ccr            * Set carry flag
  295. X    andi    #$FB,ccr        * Clear zero flag
  296. X    rts                * And return
  297. X
  298. Xget_2:
  299. X    move.l    a3,-(a7)        * Push argv onto stack
  300. X    move.l    d2,-(a7)        * Push argc onto stack
  301. X
  302. X        lea     _BSSBAS,a3          * get base of BSS
  303. X        moveq   #0,d1
  304. X        move.l  #_BSSLEN,d0         * get length of BSS in longwords
  305. X        bra.s   clr_lp              * and clear for length given
  306. Xclr_bss move.l  d1,(a3)+
  307. Xclr_lp  dbf     d0,clr_bss
  308. X
  309. Xdomain:
  310. X    jsr    main(PC)        * Call main(argc,argv)
  311. X        moveq.l #0,d0               * Set successful status
  312. X        bra.s   exit2
  313. X
  314. Xexit:
  315. X_exit:
  316. XXCEXIT:
  317. X        move.l  4(SP),d0        * Extract return code
  318. Xexit2:
  319. X        move.l  d0,-(a7)
  320. X        move.l  AbsExecBase.W,a6
  321. X        move.l  DOSBase(A4),a1
  322. X        callsys CloseLibrary            * Close Dos library
  323. X
  324. X*------ this rts sends us back to DOS:
  325. XexitToDOS:
  326. X        MOVE.L  (A7)+,D0
  327. X        movea.l _StackPtr(a4),SP        * Restore stack ptr
  328. X        movem.l (a7)+,d1-d6/a0-a6
  329. X        rts
  330. X
  331. X*-----------------------------------------------------------------------
  332. X* Global definitions
  333. X*
  334. X        csect   __MERGED,1,,2,2
  335. X*
  336. X        xdef    NULL,SysBase,LoadAddress,DOSBase
  337. X        xdef    _oserr,_OSERR,_ONBREAK
  338. X        xdef    _ProgramName,_StackPtr,_base
  339. X*
  340. XNULL           dc.l    0
  341. X_base          dc.l    0
  342. X_oserr         equ     *
  343. X_OSERR         dc.l    0
  344. X_ONBREAK       dc.l    0
  345. XSysBase        dc.l    0
  346. XLoadAddress    dc.l    0
  347. X_StackPtr      dc.l    0
  348. XDOSBase        dc.l    0
  349. X_ProgramName   dc.l    0
  350. XDOSName        dc.b    'dos.library',0
  351. X
  352. X        END
  353. SHAR_EOF
  354. echo "extracting unshar.c"
  355. sed 's/^X//' << \SHAR_EOF > unshar.c
  356. X/*
  357. X *                     Unshar (C) Copyright Eddy Carroll 1988
  358. X *                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  359. X * Usage: Unshar {-o} <filename> ...
  360. X *
  361. X * Extracts files from a SHAR'd archive.
  362. X *
  363. X * This utility has a few advantages over the version of SH on Fish Disk 92.
  364. X * For a start, it doesn't crash if it gets a slightly unusual format! It
  365. X * also has a (limited) capability for extracting files from shar archives
  366. X * which use 'SED' rather than 'CAT' (typically, this is done so that
  367. X * each line in the file may be prefixed with an 'X' or similar, so that
  368. X * indentation is preserved). Unshar will spot 'SED' lines, and treat them
  369. X * the same as 'CAT' (allowing for different parameters of course) with
  370. X * the exception that any leading characters matching the string specified
  371. X * in the SED command are discarded.
  372. X *
  373. X * Unshar checks files being extracted to see if they are to be stored
  374. X * within a sub-directory. If they are, and the sub-directory does not
  375. X * already exist, it is created.
  376. X *
  377. X * One other small addition is that any filenames which are prefixed with
  378. X * the characters "./" have these characters removed. Some shar files
  379. X * use this prefix to ensure that the files are stored in the current
  380. X * directory.
  381. X *
  382. X * Files are extracted into the current directory. As each file is extracted,
  383. X * an appropriate message is printed on the screen. If the file already
  384. X * exists, the user is warned and given the chance to avoid overwriting it
  385. X * "Overwrite file (Yes/No/All)? ". The default is Yes. If All is selected,
  386. X * then this prompt is supressed for the rest of the current file. It may
  387. X * be disabled for all the files by specifying the -o switch on the
  388. X * command line.
  389. X * 
  390. X * DISTRIBUTION
  391. X * I retain copyright rights to this source code, though it may be _freely_
  392. X * distributed. The executable file created from this source code is in
  393. X * the Public Domain and may be distributed without any restrictions.
  394. X *
  395. X */
  396. X
  397. X/* Assumes Lattice V4.0 - should work with Aztec using 32 bit ints */
  398. X
  399. X#include <exec/types.h>
  400. X#include <libraries/dos.h>
  401. X#include <proto/dos.h>
  402. X
  403. X#define YES            1
  404. X#define NO            0
  405. X#define CR            '\015'
  406. X#define EOL            '\012'
  407. X#define SINGLEQUOTE '\''
  408. X#define DOUBLEQUOTE '\042'
  409. X
  410. Xchar HelpMsg[] = "\
  411. XUnshar by Eddy Carroll 1988 Public Domain, extracts files from shar archives.\
  412. X\n\
  413. XUsage: unshar {-overwrite} <filename> ...\n";
  414. X
  415. Xchar DiskMsg[]  = "Unshar aborted - Disk write error (disk full?)\n";
  416. Xchar ErrorMsg[] = "Unshar: Invalid CAT or SED command at line ";
  417. X
  418. Xint linenum;
  419. Xint CtrlC = NO;
  420. X
  421. X
  422. X/* 
  423. X * Note - if you are using any 'C'-type memory allocators, or any C library
  424. X * functions which might conceivably allocate memory for you, delete the
  425. X * following line. If you are sticking to pure AmigaDOS calls, leave it
  426. X * in, and save yourself 1K.
  427. X *
  428. X */
  429. X
  430. Xvoid MemCleanup(){}
  431. X
  432. X/*
  433. X * --------------------------------------------------------------------------
  434. X * The following block may be removed `as-is' and used in other programs.
  435. X * It provides basic buffered i/o on two files, an input file and an output
  436. X * file. It also provides output to the current standard output via
  437. X * print. Buffering is done using buffers of size MAXBUF.
  438. X *
  439. X * The following routines are provided:
  440. X *
  441. X * getc() returns an integer corresponding to the next character read from
  442. X * infile, or EOF if the end of file has been reached.
  443. X *
  444. X * putc(c) outputs a character to outfile. putc(EOF) flushes the current
  445. X * output buffer to outfile, and should be called just before closing the
  446. X * file.
  447. X *
  448. X * getline() returns a pointer to a string containing the next line
  449. X * read in from infile. getline() also checks for CTRL-C via chkabort()
  450. X * 
  451. X * putline(s) outputs a string to outfile, returning non-zero if an
  452. X * error occurred during the write.
  453. X *
  454. X * flushin() resets getc() and getline() for input from a new file
  455. X *
  456. X * input() returns a pointer to a string containing a line from stdin.
  457. X *
  458. X * print(s) prints a message on standard output.
  459. X *
  460. X * print3(s1,s2,s3) outputs three strings on standard output.
  461. X *
  462. X * numtostr(n) returns a pointer to the ascii representation of n.
  463. X *
  464. X * Special Notes
  465. X * ~~~~~~~~~~~~~
  466. X * You should ensure that you use the filenames 'infile' and 'outfile'
  467. X * when you are opening the input and output files in main(). Also,
  468. X * do not #define EOF or MAXBUF elsewhere in your program.
  469. X *
  470. X */
  471. X
  472. X#define EOF        -1
  473. X#define MAXBUF    4096
  474. X
  475. XLONG infile, outfile, Open(), Input(), Output(), Read();
  476. XLONG maxin = MAXBUF, maxout = MAXBUF, inbuf = MAXBUF, outbuf = 0;
  477. Xunsigned char inbuffer[MAXBUF], outbuffer[MAXBUF];
  478. Xint diskerror = NO;
  479. X
  480. X/*
  481. X * int getc()
  482. X * Returns next character from infile, or EOF if end of file.
  483. X *
  484. X */
  485. X
  486. Xint getc()
  487. X{
  488. X    if (!maxin)
  489. X        return (EOF);
  490. X
  491. X    if (inbuf >= maxin) {
  492. X        maxin = Read(infile, inbuffer, MAXBUF);
  493. X        inbuf = 0;
  494. X        if (!maxin)
  495. X            return (EOF);
  496. X    }
  497. X    return (inbuffer[inbuf++]);
  498. X}
  499. X
  500. X/* 
  501. X * Prepares getc() for input from a new file
  502. X *
  503. X */
  504. X
  505. X#define flushin() maxin = MAXBUF, inbuf = MAXBUF;
  506. X
  507. X/*
  508. X * putc(c)
  509. X * Outputs character C to disk. If C is an EOF, then the output is flushed.
  510. X * If error detected on Write, then all future writes are ignored until
  511. X * an EOF is output, and diskerror is set to YES.
  512. X *
  513. X */
  514. X
  515. Xvoid putc(c)
  516. Xint c;
  517. X{
  518. X    if (c == EOF)
  519. X        maxout = outbuf;
  520. X    else
  521. X        outbuffer[outbuf++] = c;
  522. X
  523. X    if (outbuf >= maxout) {
  524. X        if (!diskerror && Write(outfile, outbuffer, maxout) == -1) {
  525. X            if (c == EOF)
  526. X                diskerror = NO;
  527. X            else
  528. X                diskerror = YES;
  529. X        }
  530. X        outbuf = 0;
  531. X        maxout = MAXBUF;
  532. X    }
  533. X}
  534. X
  535. X/*
  536. X * print(s)
  537. X * Outputs a message to std output
  538. X *
  539. X */
  540. X
  541. Xvoid print(s)
  542. Xchar *s;
  543. X{
  544. X    Write(Output(),s,strlen(s));
  545. X}
  546. X
  547. X/*
  548. X * Outputs three strings to std output.
  549. X * Useful for sequences like print3("string", variable, "string");
  550. X *
  551. X */
  552. X
  553. Xvoid print3(s1,s2,s3)
  554. Xchar *s1,*s2,*s3;
  555. X{
  556. X    print(s1);
  557. X    print(s2);
  558. X    print(s3);
  559. X}
  560. X
  561. X/*
  562. X * Reads in a line from current infile into string, and returns a pointer
  563. X * to that string. Returns NULL if EOF encountered.
  564. X *
  565. X */
  566. X
  567. Xchar *getline()
  568. X{
  569. X    register int ch, i = 0;
  570. X    static char line[90];
  571. X
  572. X    ch = getc();
  573. X    if (ch == EOF)
  574. X        return (NULL);
  575. X
  576. X    while (i < 80 && ch != EOF && ch != EOL) {
  577. X        line[i++] = ch;
  578. X        ch = getc();
  579. X    }
  580. X
  581. X    line[i] = '\0';
  582. X    linenum++;
  583. X    chkabort();
  584. X    return (line);
  585. X}
  586. X
  587. X
  588. X/*
  589. X * Outputs a string to the current output file (terminating it with LF).
  590. X * Returns 0 for success, non-zero for disk error
  591. X *
  592. X */
  593. X
  594. Xint putline(s)
  595. Xchar *s;
  596. X{
  597. X    while (*s)
  598. X        putc(*s++);
  599. X    putc(EOL);
  600. X    return (diskerror);
  601. X}
  602. X
  603. X
  604. X/*
  605. X * Reads a line from keyboard and returns pointer to it
  606. X *
  607. X */
  608. X
  609. Xchar *input()
  610. X{
  611. X    static char s[80];
  612. X
  613. X    s[Read(Input(),s,75)] = '\0';
  614. X    return(s);
  615. X}
  616. X
  617. X/*
  618. X * Converts integer to string and returns pointer to it.
  619. X *
  620. X */
  621. Xchar *numtostr(n)
  622. Xint n;
  623. X{
  624. X    static char s[20];
  625. X    int i = 19;
  626. X
  627. X    s[19] = '\0';
  628. X    if (n)
  629. X        while (n)
  630. X            s[--i] = '0' + (n % 10), n /= 10;
  631. X    else
  632. X        s[--i] = '0';
  633. X    return(&s[i]);
  634. X}
  635. X
  636. X/*
  637. X * -----------------------* End of Buffered IO routines *--------------------
  638. X */
  639. X
  640. X
  641. X/*
  642. X * index(s,c,skip)
  643. X *
  644. X * Like standard Unix index(), but skips over quotes if skip == true.
  645. X * Also skips over chars prefixed by a \.
  646. X * Returns pointer to first occurance of char c inside string s, or NULL.
  647. X *
  648. X */
  649. X
  650. Xchar *index(s,c,skip)
  651. Xchar *s,c;
  652. Xint skip;
  653. X{
  654. X    register char *p = s;
  655. X    register int noquotes = YES, literal = NO;
  656. X
  657. X    while (*p) {
  658. X        if (literal) {
  659. X            literal = NO;
  660. X            p++;
  661. X        } else {
  662. X            if (skip && ((*p == SINGLEQUOTE) || (*p == DOUBLEQUOTE)))
  663. X                noquotes = !noquotes;
  664. X            if (noquotes && (*p == c))
  665. X                return(p);
  666. X            literal = (*p == '\\');
  667. X            p++;
  668. X        }
  669. X    }
  670. X    return (NULL);
  671. X}
  672. X
  673. X
  674. X/*
  675. X * getname(s1,s2,mode)
  676. X *
  677. X * Extracts a string from start of string s1 and stores it in s2. Leading
  678. X * spaces are discarded, and quotes, if present, are used to indicate the
  679. X * start and end of the filename. If mode is MODE_FILE, then if the name
  680. X * starts with either './' or '/', this prefix is stripped. This doesn't
  681. X * happen if the mode is MODE_TEXT. A pointer to the first character after
  682. X * the string in s1 is returned. In addition, any characters prefixed with
  683. X * are passed through without checking.
  684. X *
  685. X */
  686. X
  687. X#define MODE_FILE 1
  688. X#define MODE_TEXT 2
  689. X
  690. Xchar *getname(s1,s2,mode)
  691. Xchar *s1,*s2;
  692. X{
  693. X    char endchar = ' ';
  694. X
  695. X    while (*s1 == ' ')
  696. X        s1++;
  697. X
  698. X    if (*s1 == SINGLEQUOTE || *s1 == DOUBLEQUOTE)
  699. X        endchar = *s1++;
  700. X
  701. X    if (mode == MODE_FILE) {
  702. X        if (s1[0] == '.' && s1[1] == '/')
  703. X            s1 += 2;
  704. X        while (*s1 == '/')
  705. X            s1++;
  706. X    }
  707. X
  708. X    while (*s1 && *s1 != endchar) {
  709. X        if (*s1 == '\\' && *(s1+1))
  710. X            s1++;
  711. X        *s2++ = *s1++;
  712. X    }
  713. X    *s2 = '\0';
  714. X
  715. X    if (*s1 == endchar)
  716. X        return(++s1);
  717. X    else
  718. X        return(s1);
  719. X}
  720. X
  721. X
  722. X/*
  723. X * checkfordir(filename)
  724. X *
  725. X * Checks filename to see if it is inside a subdirectory. If it is, then
  726. X * checks if subdirectory exists, and creates it if it doesn't.
  727. X *
  728. X */
  729. X
  730. Xvoid checkfordir(filename)
  731. Xchar *filename;
  732. X{
  733. X    char dir[80], *p;
  734. X    int i, x;
  735. X    long dirlock, Lock(), CreateDir();
  736. X
  737. X    p = filename;
  738. X
  739. X    while (p = index(p, '/', 1)) {
  740. X
  741. X        /* Dir exists, so copy dir part of filename into dir name area */
  742. X
  743. X        x = p - filename;
  744. X        for (i = 0; i < x; i++)
  745. X            dir[i] = filename[i];
  746. X        dir[i] = '\0';
  747. X
  748. X        /* Now, see if directory exists, if not then create */
  749. X        if ((dirlock = Lock(dir,ACCESS_READ)) == NULL) {
  750. X            dirlock = CreateDir(dir);
  751. X            if (dirlock) {
  752. X                print3("Creating directory ", dir, "\n");
  753. X            }
  754. X        }
  755. X        if (dirlock)
  756. X            UnLock(dirlock);
  757. X
  758. X        p++;
  759. X    }
  760. X}
  761. X
  762. X
  763. X/*
  764. X * Extracts all stored files from a shar file. Returns 0 for success,
  765. X * non-zero if disk error occurred. The echofilename parameter, if non-zero,
  766. X * causes the name of each shar file to be output before unsharing.
  767. X * If overwrite is non-zero, then existing files are overwritten without
  768. X * any warning.
  769. X *
  770. X */
  771. X
  772. Xint unshar(sharfile, echofilename, overwrite)
  773. Xchar *sharfile;
  774. Xint echofilename, overwrite;
  775. X{
  776. X    register char *s, *p;
  777. X    char endmarker[100], filename[100],sedstring[100];
  778. X    int endlen, stripfirst, startfile, found = NO, err = NO, skip, sedlen;
  779. X    long filelock, Lock();
  780. X
  781. X    if ((infile = Open(sharfile, MODE_OLDFILE)) == NULL) {
  782. X        print3("Can't open file ", sharfile, " for input\n");
  783. X        return(0);
  784. X    }
  785. X
  786. X    linenum = 0;
  787. X    if (echofilename)
  788. X        print3("\033[7m Shar file: ", sharfile, " \033[0m\n");
  789. X
  790. X    while (!err && !CtrlC && (s = getline()) != NULL) {
  791. X        startfile = NO;
  792. X        if (strncmp(s,"cat ",4) == 0) {
  793. X            startfile  = YES;
  794. X            stripfirst = NO;
  795. X        }
  796. X        if (strncmp(s,"sed ",4) == 0) {
  797. X            startfile  = YES;
  798. X            stripfirst = YES;
  799. X            sedlen = 0;
  800. X            if ((p = index(s,'^',0)) != NULL) {
  801. X                while (*(++p) && *p != '/')
  802. X                    sedstring[sedlen++] = *p;
  803. X            } 
  804. X        }
  805. X
  806. X        if (startfile) {    
  807. X            if (found == NO) {
  808. X                found = YES;
  809. X            }
  810. X            if ((p = index(s,'>',1)) == NULL) {
  811. X                print3(ErrorMsg, numtostr(linenum), "\n");
  812. X            } else {
  813. X                getname(++p,filename,MODE_FILE);
  814. X                p = s;
  815. X                while ((p = index(p,'<',1)) && (p[1] != '<'))
  816. X                    ;
  817. X                if (p)
  818. X                    getname(p+2,endmarker,MODE_TEXT);
  819. X
  820. X                endlen = strlen(endmarker);
  821. X
  822. X                if (strlen(filename) && endlen) {
  823. X
  824. X                    checkfordir(filename);
  825. X
  826. X                    /* Found a valid line so perform extract */
  827. X
  828. X                    /* Check if file exists */
  829. X
  830. X                    skip = NO;
  831. X                    if (!overwrite) {
  832. X                        filelock = Lock(filename, ACCESS_READ);
  833. X                        if (filelock) {
  834. X                            UnLock(filelock);
  835. X                            print3("Overwrite file ", filename,
  836. X                                " (Yes, [No], All)? ");
  837. X
  838. X                            switch (tolower(*input())) {
  839. X
  840. X                            case 'a':
  841. X                                overwrite = YES;
  842. X                                break;
  843. X                            case 'y':
  844. X                                skip = NO;
  845. X                                break;
  846. X                            default:
  847. X                                skip = YES;
  848. X                                break;
  849. X                            }
  850. X                        }
  851. X                    }
  852. X
  853. X                    if ((outfile = Open(filename,MODE_NEWFILE)) == NULL)
  854. X                        print3("Couldn't open file ",filename," for output\n");
  855. X                    else {
  856. X                        if (!skip)
  857. X                            print3("Unsharing file ", filename, "\n");
  858. X                        s = getline();
  859. X                        err = NO;
  860. X                        while (s && strncmp(s,endmarker,endlen) && !CtrlC) {
  861. X                            if (stripfirst && !strncmp(sedstring,s,sedlen))
  862. X                                s += sedlen;
  863. X                            if (!skip && (err = putline(s)))
  864. X                                break;
  865. X                            s = getline();
  866. X                        }
  867. X                        putc(EOF);
  868. X                        if (err)
  869. X                            print(DiskMsg);
  870. X                        Close(outfile);
  871. X                    }
  872. X                } else
  873. X                    print(ErrorMsg, numtostr(linenum), "\n");
  874. X            }
  875. X        }
  876. X    }
  877. X    if (!err && !CtrlC)
  878. X        if (found)
  879. X            print("Unshar done\n");
  880. X        else
  881. X            print("No files to unshar\n");
  882. X    Close(infile);
  883. X    flushin();
  884. X    return(err);
  885. X}
  886. X
  887. X/*
  888. X * New handler for Ctrl-C. Simply sets global variable to true and exits.
  889. X *
  890. X */
  891. X
  892. Xint brk()
  893. X{
  894. X    CtrlC = YES;
  895. X    return (0);
  896. X}
  897. X
  898. X/*
  899. X * Start of mainline
  900. X *
  901. X */
  902. X
  903. Xint main(argc,argv)
  904. Xint argc;
  905. Xchar *argv[];
  906. X{
  907. X
  908. X    int i, ok, overwrite = NO;
  909. X
  910. X    if ((argc == 1) || (*argv[1] == '?')) {
  911. X        print(HelpMsg);
  912. X        return (10);
  913. X    }
  914. X    if (onbreak(brk))
  915. X        exit(10);
  916. X
  917. X    for (i = 1, ok = YES; ok && i < argc && !CtrlC; i++) {
  918. X        if (*argv[i] == '-' && (argv[i][1] == 'o' || argv[i][1] == 'O'))
  919. X            overwrite = YES;
  920. X        else
  921. X            ok = !unshar(argv[i], argc > 2, overwrite);
  922. X    }
  923. X
  924. X    if (CtrlC)
  925. X        print("^C\n");
  926. X}
  927. SHAR_EOF
  928. echo "extracting unshar.doc"
  929. sed 's/^X//' << \SHAR_EOF > unshar.doc
  930. X
  931. X     UNSHAR(1)           AMIGA Programmer's Manual            UNSHAR(1)
  932. X
  933. X
  934. X
  935. X     NAME 
  936. X          unshar - extracts files from shar archives 
  937. X
  938. X     SYNOPSIS 
  939. X          unshar {-overwrite} file1 file2 ...  
  940. X
  941. X     DESCRIPTION 
  942. X          Unshar is a utility which extracts files from the ubiquitous
  943. X          Unix shar  archives.    "But  I  have umpteen zillion unshar
  944. X          utilities already", I hear you shout.  Well, maybe  so,  but
  945. X          this one has the following advantages: 
  946. X
  947. X               - Small and fast 
  948. X               - Handles many cat and sed formats 
  949. X               - Allows extraction of subdirectories 
  950. X               - Understands ./file type filenames 
  951. X               - Exits cleanly with CTRL-C 
  952. X
  953. X          The total code size is only slightly over 4K, for those with
  954. X          packed C  directories.  It treats quotes and imbedded escape
  955. X          sequences intelligently and handles  all  the  cat  and  sed
  956. X          formats  I've  ever seen, including sed commands which strip
  957. X          off more than one letter.  There are probably a few  obscure
  958. X          shar's  out  there  it  won't  handle,  but I've yet to find
  959. X          them.  
  960. X
  961. X          Invoke unshar with as many filenames as you like.    The  -o
  962. X          flag  controls  how  unshar  handles the extraction of files
  963. X          which already exist.  It can appear anywhere on the  command
  964. X          line,  and  only  affects those files which appear after it.
  965. X          Normally, if extracting a file would overwrite  an  existing
  966. X          file,  unshar  will  ask  you  how  it  should  handle this.
  967. X          Entering 'Y' will overwrite the existing file, 'N' will skip
  968. X          past this file without extracting it, and 'A' will overwrite
  969. X          this file, and  also  any  other  existing  files  from  the
  970. X          current shar file without prompting you again.  If you don't
  971. X          like prompts, specifying -o on the command line makes unshar
  972. X          overwrite all existing files.  
  973. X
  974. X     OPERATION 
  975. X          Unshar  scans  through each archive specified on the command
  976. X          line, looking for lines beginning with 'cat' or  'sed'.  All
  977. X          other lines  are  ignored.   In particular, 'echo' lines are
  978. X          not echoed.  This way, you don't  get  a  load  of  messages
  979. X          which  are  in  any  case  fairly  meaningless,  because the
  980. X          operations they  are  describing  are  unsupported  by  most
  981. X          unshars.  
  982. X
  983. X          When  a  shar  archive  contains  a  file  for  which a full
  984. X          pathname is given (as in source/file.c for  example)  unshar
  985. X          will create  whatever  directories  are  necessary.  It also
  986. X          strips  off  leading  /'s  and  ./'s,  to   make   filenames
  987. X          understandable by AmigaDOS.  
  988. X
  989. X     AUTHOR 
  990. X          Eddy Carroll 
  991. X          Internet: ecarrollcs.tcd.ie 
  992. X
  993. X
  994. X     Copyright Eddy Carroll 1989      -1-
  995. SHAR_EOF
  996. echo "extracting unshar.n"
  997. sed 's/^X//' << \SHAR_EOF > unshar.n
  998. X.TH BACKDROP 1 "AMIGA Programmer's Manual" "Copyright Eddy Carroll 1989"
  999. X.SH NAME
  1000. Xunshar - extracts files from shar archives
  1001. X.SH SYNOPSIS
  1002. Xunshar {-overwrite} file1 file2 ...
  1003. X.SH DESCRIPTION
  1004. XUnshar is a utility which extracts files from the ubiquitous Unix shar
  1005. Xarchives. "But I have umpteen zillion unshar utilities already",
  1006. XI hear you shout. Well, maybe so, but this one has the following advantages:
  1007. X
  1008. X.in +5
  1009. X- Small and fast
  1010. X.br
  1011. X- Handles many cat and sed formats
  1012. X.br
  1013. X- Allows extraction of subdirectories
  1014. X.br
  1015. X- Understands ./file type filenames
  1016. X.br
  1017. X- Exits cleanly with CTRL-C
  1018. X.in -5
  1019. X
  1020. XThe total code size is only slightly over 4K, for those with packed C
  1021. Xdirectories. It treats quotes and imbedded escape sequences intelligently
  1022. Xand handles all the cat and sed formats I've ever seen, including sed
  1023. Xcommands which strip off more than one letter. There are probably a few
  1024. Xobscure shar's out there it won't handle, but I've yet to find them.
  1025. X
  1026. XInvoke unshar with as many filenames as you like. The -o flag controls
  1027. Xhow unshar handles the extraction of files which already exist. It can
  1028. Xappear anywhere on the command line, and only affects those files which
  1029. Xappear after it. Normally, if extracting a file would overwrite an
  1030. Xexisting file, unshar will ask you how it should handle this. Entering
  1031. X'Y' will overwrite the existing file, 'N' will skip past this file without
  1032. Xextracting it, and 'A' will overwrite this file, and also any other existing
  1033. Xfiles from the current shar file without prompting you again. If you don't
  1034. Xlike prompts, specifying -o on the command line makes unshar overwrite all
  1035. Xexisting files.
  1036. X.SH OPERATION
  1037. XUnshar scans through each archive specified on the command line, looking
  1038. Xfor lines beginning with 'cat' or 'sed'. All other lines are ignored. In
  1039. Xparticular, 'echo' lines are not echoed. This way, you don't get a load
  1040. Xof messages which are in any case fairly meaningless, because the operations
  1041. Xthey are describing are unsupported by most unshars.
  1042. X
  1043. XWhen a shar archive contains a file for which a full pathname is given
  1044. X(as in source/file.c for example) unshar will create whatever directories
  1045. Xare necessary. It also strips off leading /'s and ./'s, to make filenames
  1046. Xunderstandable by AmigaDOS.
  1047. X.SH AUTHOR
  1048. XEddy Carroll
  1049. X.br
  1050. XInternet: ecarroll@cs.tcd.ie
  1051. SHAR_EOF
  1052. echo "extracting unshar.uu"
  1053. sed 's/^X//' << \SHAR_EOF > unshar.uu
  1054. X
  1055. Xbegin 644 unshar
  1056. XM```#\P`````````"``````````$```-2```)*````^D```-22.=^_DOO`#0D]
  1057. XM2"0`2?D`````+'@`!"E.`!`I3P`8D\E.KO[:)D`@#9"M``0&@````(`I0``$D
  1058. XM0^P`)'``3J[]V"E``!QF```(<&1@``#H(&L`K-'(T<@B:``0T\G3R2`"<@`2$
  1059. XM&2E)`"#0@5*`0F=2@`)`__Z?P%6`0G<(`"`"4X#4@1^R```@`%."4<C_]A^\V
  1060. XM`"`@`%."'[$@`"``4<K_^")/G_P```"`)$\F2G0`831E$F?Z0>G__V$<82AF;
  1061. XM_$(I__]@ZB!)80YA&F3\0BG__V$29OQGV"3(4D(,0@`@8R)P;F!0$!EG)@P`B
  1062. XM`")G%@P``"!G"@P```EG!`P```H"/``>3G4`/``!`CP`^TYU+PLO`D?Y```"7
  1063. XME'(`(#P```B#8`(FP5'(__Q.N@AB<`!@!"`O``0O`"QX``0B;``<3J[^8B`?_
  1064. XM+FP`&$S??WY.=0``3G5(YS`"2JP!"F8$</]@1B(L`1*RK`$*;2PB+`*80>P"[
  1065. XMH"0()CP``!``+&P`'$ZN_]8I0`$*<``I0`$22JP!"F8$</]@$$'L`J#1[`$2,
  1066. XM4JP!$G``$!!,WT`,3G5.50``2.<P`B(M``@,@?____]F"B`L`18I0`$.8!!![
  1067. XM[!*@(DC3[`$64JP!%A*!(BP!#B0L`1:T@6U$2JP!&F8R(BP"G$'L$J`D""8LB
  1068. XM`0XL;``<3J[_T%*`9A@,K?____\`"&8(<``I0`$:8`9P`2E``1I"K`$6*7P`"
  1069. XM`!```0Y,WT`,3EU.=4Y5__A(YS`"+&P`'$ZN_\0O0``,+RT`"$ZZ"9Q83R]`4
  1070. XM`!`B+P`,)"T`""8O`!`L;``<3J[_T$S?0`Q.74YU3E4``"\M``AAN%A/+RT`R
  1071. XM#&&P6$\O+0`08:A83TY=3G5.5?_X2.<#`'P`80#^MBX`#(?_____9@1P`&!"D
  1072. XM#(8```!0;"0,A_____]G'`R'````"F<40>PBH-'&4H8@!Q"`80#^@"X`8-1!S
  1073. XM["*@T<9"$%*L`I1.N@F"0>PBH"`(3-\`P$Y=3G5.50``(&T`"$H09Q00$$B`C
  1074. XM2,!2K0`(+P!A`/Z<6$]@Y$AX``IA`/Z06$\@+`$:3EU.=4Y5__Q(YS`"+&P`P
  1075. XM'$ZN_\HO0``,(B\`#$'L(OHD"'9++&P`'$ZN_]9!["+Z(DC3P$(1(`A,WT`,L
  1076. XM3EU.=4Y5__AP$RM`__Q"+"-=2JT`"&<\2JT`"&=(4ZW__$'L(TK1[?_\("T`*
  1077. XM"'(*+T@``$ZZ!XX&@0```#`@;P``$($@+0`(<@I.N@=X*T``"&#$4ZW__$'L&
  1078. XM(THB2-/M__P2O``P0>PC2M'M__P@"$Y=3G5.5?_T2.<C("1M``A^`7P`2A)G8
  1079. XM3DJ&9P9\`%**8/)*K0`09QH2$@P!`"=G!@P!`")F#$J'5\!$`$B`2,`N`$J'>
  1080. XM9PX2$A0M``^T`68$(`I@%`P2`%Q7P$0`2(!(P"P`4HI@KG``3-\$Q$Y=3G5.`
  1081. XM5?_^2.<@`!M\`"#__R!M``@,$``@9@92K0`(8/`@;0`($A`,`0`G9P8,`0`BQ
  1082. XM9@A2K0`(&T'__PRM`````0`09B8@;0`(#!``+F8,#"@`+P`!9@14K0`((&T`:
  1083. XM"`P0`"]F!E*M``A@\"!M``A*$&<N$A`4+?__M`%G)`P!`%QF"DHH``%G!%*MQ
  1084. XM``@@;0`((FT`#!*04JT`"%*M``Q@RB!M``Q"$"!M``@2$+(M__]F#%*M``@@N
  1085. XM;0`((`A@!"`(3G%,WP`$3EU.=4Y5_Z!(YR`"*VT`"/^L2'@``4AX`"\O+?^L:
  1086. XM80#^L$_O``PK0/^L2H!G``"0D*T`"$*M_Z@K0/^D(BW_J+*M_Z1L$"!M``@;]
  1087. XML!@`&+!2K?^H8.8@+?^H0C4(L$'M_[`B"'3^+&P`'$ZN_ZPK0/^@2JW_H&8LE
  1088. XM0>W_L"((+&P`'$ZN_X@K0/^@2JW_H&<42&P!,DAM_[!(;`$>80#\SD_O``Q*V
  1089. XMK?^@9PPB+?^@+&P`'$ZN_Z92K?^L8`#_5DS?0`1.74YU3E7^K$CG(")P`"M`7
  1090. XM_K@K0/Z\(BT`""0\```#[2QL`!Q.KO_B*4`"F$JL`IAF&DAL`48O+0`(2&P!Z
  1091. XM-&$`_&I/[P`,<`!@``-J0JP"E$JM``QG%$AL`60O+0`(2&P!4F$`_$9/[P`,U
  1092. XM2JW^N&8``OY*K`$&9@`"]F$`_$XD0+3\``!G``+H0JW^P$AX``1(;`%L+PI.7
  1093. XMN@1.3^\`#$J`9@IP`2M`_L!"K?[$2'@`!$AL`7(O"DZZ!"Y/[P`,2H!F3'`!P
  1094. XM<@`O`4AX`%XO"BM`_L0K0/[`*T'^L&$`_3)/[P`,*T#_^$J`9R12K?_X(&W_\
  1095. XM^$H09Q@2$`P!`"]G$$/M_LS3[?ZP4JW^L!*!8-Q*K?[`9P#_5DJM_KQF!G`!)
  1096. XM*T#^O$AX``%(>``^+PIA`/S@3^\`#"M`__A*@&8@+RP"E&$`_%Q83TAL`7@O#
  1097. XM`$AL`-EA`/M83^\`#&``_Q!2K?_X(&W_^$AX``%(;?\P+PAA`/T*3^\`#"M*W
  1098. XM__A(>``!2'@`/"\M__AA`/R&3^\`#"M`__A*@&<*($`,*``\``%FVDJM__AGW
  1099. XM&"!M__A4B$AX``)(;?^4+PAA`/S"3^\`#$AM_Y1.N@1>6$](;?\P*T#^R$ZZ8
  1100. XM!%!83TJ`9P`!=$JM_LAG``%L2&W_,&$`_5A83T*M_K1*K0`09G)![?\P(@ATN
  1101. XM_BQL`!Q.KO^L*T#^K$JM_JQG6"(M_JPL;``<3J[_IDAL`8I(;?\P2&P!>F$`/
  1102. XM^GY/[P`,80#[+B!`$A!(@4C!+P%.N@,$6$\,@````'EG$`R`````868.<`$K_
  1103. XM0``08`Q"K?ZT8`9P`2M`_K1![?\P(@@D/````^XL;``<3J[_XBE``IQ*K`*<5
  1104. XM9AA(;`&R2&W_,$AL`9YA`/H43^\`#&``_<Q*K?ZT9A1(;`'02&W_,$AL`<!A@
  1105. XM`/GV3^\`#&$`^@XD0$*M_KBT_```9UHO+?[(2&W_E"\*3KH"$$_O``Q*@&=$8
  1106. XM2JP!!F8^2JW^Q&<:+RW^L"\*2&W^S$ZZ`>Y/[P`,2H!F!-7M_K!*K?ZT9A`O0
  1107. XM"F$`^B!83RM`_KA*@&8(80#YK"1`8*!(>/__80#XO%A/2JW^N&<*2&P`J6$`%
  1108. XM^3)83R(L`IPL;``<3J[_W&``_1XO+`*480#Z2EA/2&P!TB\`2&P`V6$`^0A/U
  1109. XM[P`,8`#\_DJM_KAF(DJL`09F'$JM_KQG#$AL`=1A`/CF6$]@"DAL`>)A`/C:0
  1110. XM6$\B+`*8+&P`'$ZN_]P@/```$``I0`$**4`!$B`M_KA,WT0$3EU.=7`!*4`!U
  1111. XM!G``3G5.5?_T2.<X`$*M__0,K0````$`"&<0(FT`#"!I``00$`P``#]F$$AL.
  1112. XM`#!A`/AZ6$]P"F```+!(>O^^3KH"B%A/2H!G"DAX``I.NO=:6$]P`2M`__@KO
  1113. XM0/_\2JW_^&=V(BT`""0M__RT@6QJ2JP!!F9D(`+E@")M``P@<0@`%A`,`P`M8
  1114. XM9AA2B!`0#```;V<&#```3V8(<`$K0/_T8#(@`N6`#($````"7L%$`4B!2,$O%
  1115. XM+?_T+P$O,0@`80#[A$_O``Q*@%?!1`%(@4C!*T'_^%*M__Q@A$JL`09G"DAL^
  1116. XM`?9A`/?&6$],WP`<3EU.=4CG,#(L>0```I`@;P`8(F\`'"1O`"`F;P`D("\`(
  1117. XM*"(O`"PD+P`P)B\`-$ZN_J1,WTP,3G5.5?_\2JT`$&<P(&T`"$H09R@B;0`,J
  1118. XM2A%G('``$!!2K0`(<@`2$5*M``R0@2M`__Q*@&8F4ZT`$&#*2JT`$&<8(&T`S
  1119. XM"$H09P1P`6`.(&T`#$H09P1P_V`"<`!.74YU```@+P`$#```06T*#```6FX$H
  1120. XM!@``($YU``!*@&H``!Y$@$J!:@``#$2!80``($2!3G5A```81(!$@4YU2H%J(
  1121. XM```,1(%A```&1(!.=2\"2$$T`68``")(0$A!2$(T`&<```:$P3`"2$`T`(3!J
  1122. XM,`)(0C(")!].=2\#=A`,00"`9```!N&944,,00@`9```!NF964,,02``9```A
  1123. XM!N6954-*06L```;CF5-#-`#FJ$A"0D+FJDA#@,$V`#`"-`-(0<3!D()D```(!
  1124. XM4T/0@63^<@`R`TA#Y[A(0,-`)A\D'TYU(&\`!$H89OQ3B)'O``0@"$YU``!.?
  1125. XM5?_X2.<!('X`1>PC8+ZL`?QL'DJ29Q0(*@`"``-G`F`*+RH`!$ZZ`/Q83U*'!
  1126. XM4(I@W"\M``PO+0`(3KKT^%!/3-\$@$Y=3G5P`6`.(&T`#$H09P0@+P`$9@8@N
  1127. XM/```#,0CP`````QP`$YU``!.5?_\<``B/```,``L>``$3J[^S@*````P`"M`7
  1128. XM__Q*@&8$<`!@)$JL``QG&B!L``Q.D$J`9@1P`&`00J=(>``43KK_4E!/("W_Q
  1129. XM_$Y=3G5AL$YU``````````!P84JL`I!F$D/L`GQP`"QX``1.KOW8*4`"D"ELU
  1130. XM`"`"/$AX`#Q(>`#Z<``O`"\`2&P":$AL`DY(;`(P+P!.NOUX3^\`(%.`9P1PB
  1131. XM_V`"<`!.=0``3G4`````````````3E4``$JL``QG!$ZZ_SPB+0`(+&P`'$ZNQ
  1132. XM_]QP`$Y=3G4`(%.`9P1P80```^P````!````````#%@````$`````0``#%X`K
  1133. XM``I^```!%`````X````````#\@```^H```"E````````````````````````R
  1134. XM````````````````````````9&]S+FQI8G)A<GD`56YS:&%R(&)Y($5D9'D@;
  1135. XM0V%R<F]L;"`Q.3@X(%!U8FQI8R!$;VUA:6XL(&5X=')A8W1S(&9I;&5S(&9RE
  1136. XM;VT@<VAA<B!A<F-H:79E<RX*57-A9V4Z('5N<VAA<B![+6]V97)W<FET97T@#
  1137. XM/&9I;&5N86UE/B`N+BX*`%5N<VAA<B!A8F]R=&5D("T@1&ES:R!W<FET92!EI
  1138. XM<G)O<B`H9&ES:R!F=6QL/RD*`%5N<VAA<CH@26YV86QI9"!#050@;W(@4T5$$
  1139. XM(&-O;6UA;F0@870@;&EN92```````````!`````0````$````````````$-R!
  1140. XM96%T:6YG(&1I<F5C=&]R>2``"@!#86XG="!O<&5N(&9I;&4@```@9F]R(&EN4
  1141. XM<'5T"@`;6S=M(%-H87(@9FEL93H@```@&ULP;0H``&-A="```'-E9"````H``
  1142. XM3W9E<G=R:71E(&9I;&4@`"`H665S+"!;3F]=+"!!;&PI/R``0V]U;&1N)W0@N
  1143. XM;W!E;B!F:6QE(``@9F]R(&]U='!U=`H``%5N<VAA<FEN9R!F:6QE(``*``H`W
  1144. XM56YS:&%R(&1O;F4*``!.;R!F:6QE<R!T;R!U;G-H87(*`%Y#"@```````"@JL
  1145. XM*B!5<V5R($%B;W)T(%)E<75E<W1E9"`J*@``__\````.``X````````"````C
  1146. XM``#__P````0`!``````````````"'$-/3E1)3E5%``#__P````0`!```````/
  1147. XM``)$`````$%"3U)4`/__````!``$`````````F(`````:6YT=6ET:6]N+FQI.
  1148. XM8G)A<GD````````````#[`````0````!```"=````EH```)````"*```````2
  1149. X#``/RU
  1150. X``
  1151. Xend
  1152. Xsize 4188
  1153. SHAR_EOF
  1154. echo "End of archive 1 (of 1)"
  1155. # if you want to concatenate archives, remove anything after this line
  1156. exit
  1157.